#![windows_subsystem = "windows"]
#[macro_use]
use aes::Aes128;
use async_std::{
    io,
    net::{TcpListener, TcpStream, ToSocketAddrs},
    prelude::*,
    sync::channel,
    task,
};
use block_modes::block_padding::Pkcs7;
use block_modes::{BlockMode, Cbc};
use env_logger::Env;
use hex_literal::hex;
use iced::{
    button, scrollable, slider, text_input, Align, Application, Button, Checkbox, Color, Column,
    Command, Container, Element, Font, HorizontalAlignment, Length, Row, Scrollable, Settings,
    Space, Subscription, Text, TextInput,
};
use iced_futures::futures;
use rand::Rng;
use serde::{Deserialize, Serialize};
use std::time::Duration;

type TcpResult<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
type AesCbc = Cbc<Aes128, Pkcs7>;

const COMMAND_CONFIG: u8 = 0;
const COMMAND_ACTIVATE: u8 = 1;
const COMMAND_LIGHTEN: u8 = 2;
const COMMAND_UNLIGHTEN: u8 = 3;

pub fn main() {
    Wisight::run(Settings {
        default_font: Some(include_bytes!(
            "Myriad Pro Regular.ttf"
        )),
        ..Settings::default()
    })
}

// Message
#[derive(Debug, Clone)]
pub enum Message {
    Child(ChildState),
    Loaded(Result<SavedState, LoadError>),
    Light(usize, LightMessage),
    ChangePasswordBotton,
    LoginBotton,
    AddLight,
    SaveBotton,
    FilterChanged(Filter),
    Saved(Result<(), SaveError>),
    Connected(Option<(TcpStream, TcpStream)>),
    Inited(bool),
    Empty,
    ConfigReturn(Option<(TcpStream, Light)>),
    RecvMessage(RecvJSON),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RecvJSON {
    mac: String,
    command: u8,
}

#[derive(Debug, Clone)]
pub enum ChildState {
    Secure(bool),
    LoginPasswordText(String),
    ChangePasswordText(String),
    AddName(String),
}

#[derive(Debug, Clone)]
pub enum LightMessage {
    Working(bool),
    Edit,
    Delete,
    NameEdited(String),
    NameEditedFinish,
    MACEdited(String),
    MACEditedFinish,
    LinkMACEdited(usize, String),
    LinkMACEditedFinish(usize),
    EditFinish,
}

#[derive(Debug, Clone)]
pub enum SendMessage {
    ConfigMessage(String, Vec<Mac>),
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Address {
    dest_addr: String,
    command: u8,
    link_mac: Vec<Mac>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Mac {
    mac: String,
}

impl Mac {
    fn new(s: String) -> Mac {
        Mac { mac: s }
    }
}

// Widight the main gui struct
pub struct Wisight {
    page: Page,
    scroll: scrollable::State,
    password: [u8; 16],
    repassword: [u8; 16],
    lights: Vec<Light>,
    send_socket: Option<TcpStream>,
    recv_socket: Option<TcpStream>,
}

impl Wisight {
    fn new_empty() -> Wisight {
        Wisight {
            page: Page::LogIn {
                password: String::new(),
                repassword: String::new(),
                is_secure: true,
                state: text_input::State::new(),
                restate: text_input::State::new(),
                lstate: button::State::new(),
                rstate: button::State::new(),
            },
            scroll: scrollable::State::new(),
            password: [0; 16],
            repassword: [0; 16],
            lights: Vec::new(),
            send_socket: None,
            recv_socket: None,
        }
    }
}

impl Application for Wisight {
    type Executor = iced::executor::Default;
    type Message = Message;
    type Flags = ();

    fn new(_flags: ()) -> (Wisight, Command<Message>) {
        (Wisight::new_empty(), Command::none())
    }

    fn title(&self) -> String {
        String::from("Wisight - A wisdom road light")
    }

    fn update(&mut self, message: Message) -> Command<Message> {
        match message {
            Message::Child(m) => {
                self.page.update(m);
                Command::none()
            }
            Message::LoginBotton => {
                {
                    if let Page::LogIn { password, .. } = &self.page {
                        let buffer = password.as_bytes();
                        for i in 0..buffer.len() {
                            self.password[i] = buffer[i];
                        }
                        for i in buffer.len()..16 {
                            self.password[i] = 0;
                        }
                    }
                }
                self.page = Page::IO { loading: true };
                println!("Login with password{:?}", &self.password);
                Command::perform(SavedState::load(self.password), Message::Loaded)
            }
            Message::ChangePasswordBotton => {
                {
                    if let Page::LogIn {
                        password,
                        repassword,
                        ..
                    } = &self.page
                    {
                        let buffer = password.as_bytes();
                        for i in 0..buffer.len() {
                            self.password[i] = buffer[i];
                        }
                        for i in buffer.len()..16 {
                            self.password[i] = 0;
                        }
                        let buffer = repassword.as_bytes();
                        for i in 0..buffer.len() {
                            self.repassword[i] = buffer[i];
                        }
                        for i in buffer.len()..16 {
                            self.repassword[i] = 0;
                        }
                    }
                }
                self.page = Page::IO { loading: true };
                println!("Login with password{:?}", &self.password);
                Command::perform(SavedState::load(self.password), Message::Loaded)
            }
            Message::Loaded(r) => match r {
                Ok(s) => {
                    self.lights = s.lights;
                    Command::perform(accept_connection("0.0.0.0", 1591), Message::Connected)
                }
                Err(e) => match e {
                    LoadError::CipherError => {
                        println!("Password Mismatch");
                        self.page = Page::LogIn {
                            password: String::new(),
                            repassword: String::new(),
                            is_secure: true,
                            state: text_input::State::new(),
                            restate: text_input::State::new(),
                            lstate: button::State::new(),
                            rstate: button::State::new(),
                        };
                        self.password = [0; 16];
                        Command::none()
                    }
                    LoadError::FileError => {
                        println!("File Not Exist");
                        Command::perform(accept_connection("0.0.0.0", 1591), Message::Connected)
                    }
                    LoadError::FormatError => {
                        println!("Saved File Format Is Not Matched");
                        Command::perform(accept_connection("0.0.0.0", 1591), Message::Connected)
                    }
                },
            },
            Message::AddLight => {
                let mut s = String::new();
                if let Page::State { addname, .. } = &self.page {
                    s.clone_from(addname);
                }
                let mut light = Light::new();
                light.name = s;
                self.lights.push(light);
                Command::none()
            }
            Message::Light(i, s) => match &s {
                LightMessage::Delete => {
                    self.lights.remove(i);
                    Command::none()
                }
                LightMessage::EditFinish => {
                    self.lights[i].update(s);
                    Command::perform(
                        config(self.send_socket.clone().unwrap(), self.lights[i].clone()),
                        Message::ConfigReturn,
                    )
                }
                _ => {
                    self.lights[i].update(s);
                    Command::none()
                }
            },
            Message::SaveBotton => {
                let mut t = SavedState { lights: Vec::new() };
                t.lights.clone_from(&self.lights);
                let mut key = [0u8; 16];
                key.clone_from(&self.password);
                Command::perform(t.save(key), Message::Saved)
            }
            Message::Saved(r) => {
                match r {
                    Ok(_) => println!("Successfully Saved"),
                    Err(e) => println!("Failed to Save Due to {:?}", e),
                };
                Command::none()
            }
            Message::FilterChanged(f) => {
                if let Page::State { filter, .. } = &mut self.page {
                    *filter = f;
                }
                Command::none()
            }
            Message::Connected(t) => match t {
                None => Command::perform(accept_connection("0.0.0.0", 1591), Message::Connected),
                Some(t) => {
                    let (send_stream, receive_stream) = t;
                    self.send_socket = Some(send_stream);
                    self.recv_socket = Some(receive_stream);
                    let s = self.send_socket.clone();
                    Command::perform(inite(s.unwrap(), self.lights.clone()), Message::Inited)
                }
            },
            Message::Inited(b) => {
                if b {
                    self.page = Page::State {
                        addname: String::new(),
                        addstate: text_input::State::new(),
                        scroll: scrollable::State::new(),
                        filter: Filter::All,
                        all_button: button::State::new(),
                        detected_button: button::State::new(),
                        fired_button: button::State::new(),
                        free_button: button::State::new(),
                        save_button: button::State::new(),
                    };
                    Command::none()
                } else {
                    let s = self.send_socket.clone();
                    Command::perform(inite(s.unwrap(), self.lights.clone()), Message::Inited)
                }
            }
            Message::ConfigReturn(o) => {
                let (s, l) = match o {
                    None => return Command::none(),
                    Some(t) => t,
                };
                Command::perform(config(s, l), Message::ConfigReturn)
            }
            Message::RecvMessage(j) => {
                if let RecvJSON { mac, command } = j {
                    let t = match self
                        .lights
                        .iter_mut()
                        .enumerate()
                        .filter(|(_, light)| light.matched(&mac))
                        .next()
                    {
                        Some(d) => d.0,
                        None => {
                            println!("MAC Mismatch");
                            return Command::none();
                        }
                    };
                    match command {
                        COMMAND_ACTIVATE => {
                            self.lights[t].detected = true;
                        }
                        COMMAND_LIGHTEN => {
                            self.lights[t].fired = true;
                        }
                        COMMAND_UNLIGHTEN => {
                            self.lights[t].fired = false;
                            self.lights[t].detected = false;
                        }
                        _ => (),
                    }
                }
                Command::none()
            }
            Message::Empty => Command::none(),
        }
    }

    fn subscription(&self) -> Subscription<Message> {
        match self.page {
            Page::State { .. } => {
                let mut rng = rand::thread_rng();
                iced::Subscription::from_recipe(ESPListener {
                    socket: self.recv_socket.clone().unwrap(),
                    hash_code: rng.gen(),
                })
            }
            Page::LogIn { .. } | Page::IO { .. } => Subscription::none(),
        }
    }

    fn view(&mut self) -> Element<Message> {
        let Wisight { page, scroll, .. } = self;
        let title = Text::new("Wisight")
            .width(Length::Fill)
            .size(80)
            .color([0.5, 0.5, 0.5])
            .horizontal_alignment(HorizontalAlignment::Center);
        let foot0 = Text::new("Copyright (c) 2020, yezoli")
            .width(Length::Fill)
            .size(15)
            .color([0.5, 0.5, 0.5])
            .horizontal_alignment(HorizontalAlignment::Center);
        let foot1 = Text::new("https://gitee.com/yezoli/WisightServer")
            .width(Length::Fill)
            .size(15)
            .color([0.5, 0.5, 0.5])
            .horizontal_alignment(HorizontalAlignment::Center);
        let foot2 = Text::new("BSD 3-Clause License")
            .width(Length::Fill)
            .size(15)
            .color([0.5, 0.5, 0.5])
            .horizontal_alignment(HorizontalAlignment::Center);
        let lights_view = match page {
            Page::State { filter, .. } => {
                let lights = {
                    self.lights
                        .iter_mut()
                        .enumerate()
                        .filter(|(_, light)| filter.matches(light))
                        .fold(Column::new().spacing(20), |column, (i, light)| {
                            column.push(light.view(i))
                        })
                };
                Some(lights)
            }
            _ => None,
        };
        let content = Column::new()
            .max_width(800)
            .spacing(20)
            .push(title)
            .push(page.view());
        let content = match lights_view {
            None => content,
            Some(l) => content.push(l),
        }
        .push(foot0)
        .push(foot1)
        .push(foot2);
        let scrollable =
            Scrollable::new(scroll).push(Container::new(content).width(Length::Fill).center_x());
        Container::new(scrollable)
            .height(Length::Fill)
            .center_y()
            .into()
    }
}

enum Page {
    LogIn {
        password: String,
        repassword: String,
        is_secure: bool,
        state: text_input::State,
        restate: text_input::State,
        lstate: button::State,
        rstate: button::State,
    },
    State {
        addname: String,
        addstate: text_input::State,
        scroll: scrollable::State,
        filter: Filter,
        all_button: button::State,
        detected_button: button::State,
        fired_button: button::State,
        free_button: button::State,
        save_button: button::State,
    },
    IO {
        loading: bool,
    },
}

impl<'a> Page {
    fn update(&mut self, msg: ChildState) {
        match msg {
            ChildState::Secure(b) => {
                if let Page::LogIn { is_secure, .. } = self {
                    *is_secure = b;
                }
            }
            ChildState::LoginPasswordText(s) => {
                if let Page::LogIn { password, .. } = self {
                    *password = s;
                }
            }
            ChildState::ChangePasswordText(s) => {
                if let Page::LogIn { repassword, .. } = self {
                    *repassword = s;
                }
            }
            ChildState::AddName(s) => {
                if let Page::State { addname, .. } = self {
                    *addname = s;
                }
            }
        }
    }

    fn view(&mut self) -> Element<Message> {
        match self {
            Page::IO { loading } => {
                if *loading {
                    Self::container("").push(
                        Text::new("Loading...")
                            .width(Length::Fill)
                            .size(60)
                            .color([0.5, 0.5, 0.5])
                            .horizontal_alignment(HorizontalAlignment::Center),
                    )
                } else {
                    Self::container("Saving").push(
                        Text::new("Saving...")
                            .width(Length::Fill)
                            .size(60)
                            .color([0.5, 0.5, 0.5])
                            .horizontal_alignment(HorizontalAlignment::Center),
                    )
                }
            }
            Page::LogIn {
                password,
                repassword,
                is_secure,
                state,
                restate,
                lstate,
                rstate,
            } => {
                let password_input = TextInput::new(state, "Type in the password", password, |x| {
                    Message::Child(ChildState::LoginPasswordText(x))
                })
                .padding(10)
                .size(30)
                .on_submit(Message::LoginBotton);
                let password_reset =
                    TextInput::new(restate, "Reset the password", repassword, |x| {
                        Message::Child(ChildState::ChangePasswordText(x))
                    })
                    .padding(10)
                    .size(30)
                    .on_submit(Message::ChangePasswordBotton);
                let bottons = Row::new()
                    .push(
                        Button::new(
                            lstate,
                            Text::new("Reset Password")
                                .horizontal_alignment(HorizontalAlignment::Center),
                        )
                        .padding(12)
                        .min_width(100)
                        .on_press(Message::ChangePasswordBotton)
                        .style(style::Button::Secondary),
                    )
                    .push(Space::with_width(Length::Fill))
                    .push(
                        Button::new(
                            rstate,
                            Text::new("Login").horizontal_alignment(HorizontalAlignment::Center),
                        )
                        .padding(12)
                        .min_width(100)
                        .on_press(Message::LoginBotton)
                        .style(style::Button::Primary),
                    );
                Self::container("")
                    .push(if *is_secure {
                        password_input.password()
                    } else {
                        password_input
                    })
                    .push(Checkbox::new(*is_secure, "Enable password mode", |x| {
                        Message::Child(ChildState::Secure(x))
                    }))
                    .push(password_reset)
                    .push(bottons)
            }

            Page::State {
                scroll,
                save_button,
                filter,
                all_button,
                detected_button,
                fired_button,
                free_button,
                addname,
                addstate,
            } => {
                let add_light = Row::new()
                    .push(
                        TextInput::new(addstate, "Add new light", addname, move |x| {
                            Message::Child(ChildState::AddName(x))
                        })
                        .padding(10)
                        .size(30)
                        .on_submit(Message::AddLight),
                    )
                    .push(Space::with_width(Length::Units(20)))
                    .push(
                        Button::new(
                            save_button,
                            Text::new("Save").horizontal_alignment(HorizontalAlignment::Center),
                        )
                        .padding(12)
                        .min_width(100)
                        .on_press(Message::SaveBotton)
                        .style(style::Button::Primary),
                    );
                let filter_button = |state, label, filter, current_filter| {
                    let label = Text::new(label).size(16);
                    let button = Button::new(state, label).style(style::Button::Filter {
                        selected: filter == current_filter,
                    });
                    button.on_press(Message::FilterChanged(filter)).padding(8)
                };
                let content = Row::new()
                    .align_items(Align::End)
                    .width(Length::Shrink)
                    .spacing(10)
                    .push(filter_button(all_button, "All", Filter::All, *filter))
                    .push(filter_button(fired_button, "Fired", Filter::Fired, *filter))
                    .push(filter_button(
                        detected_button,
                        "Detected",
                        Filter::Detected,
                        *filter,
                    ))
                    .push(filter_button(free_button, "Free", Filter::Free, *filter));
                Self::container("").push(add_light).push(content)
            }
        }
        .into()
    }

    fn container(title: &str) -> Column<'a, Message> {
        Column::new().spacing(20).push(Text::new(title).size(50))
    }
}

#[derive(Debug, Clone)]
pub enum LightState {
    Idle {
        edit_button: button::State,
    },
    Editing {
        edit_button: button::State,
        name: text_input::State,
        mac: text_input::State,
        linked_mac0: text_input::State,
        linked_mac1: text_input::State,
        linked_mac2: text_input::State,
        linked_mac3: text_input::State,
        linked_mac4: text_input::State,
        linked_mac5: text_input::State,
        linked_mac6: text_input::State,
        linked_mac7: text_input::State,
        linked_mac8: text_input::State,
        linked_mac9: text_input::State,
        delete_button: button::State,
    },
}

impl Default for LightState {
    fn default() -> Self {
        LightState::Idle {
            edit_button: button::State::new(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Light {
    name: String,
    mac: [u8; 6],
    linked_mac0: Option<[u8; 6]>,
    linked_mac1: Option<[u8; 6]>,
    linked_mac2: Option<[u8; 6]>,
    linked_mac3: Option<[u8; 6]>,
    linked_mac4: Option<[u8; 6]>,
    linked_mac5: Option<[u8; 6]>,
    linked_mac6: Option<[u8; 6]>,
    linked_mac7: Option<[u8; 6]>,
    linked_mac8: Option<[u8; 6]>,
    linked_mac9: Option<[u8; 6]>,

    #[serde(skip)]
    namestr: String,
    #[serde(skip)]
    macstr: String,
    #[serde(skip)]
    linkedstr0: String,
    #[serde(skip)]
    linkedstr1: String,
    #[serde(skip)]
    linkedstr2: String,
    #[serde(skip)]
    linkedstr3: String,
    #[serde(skip)]
    linkedstr4: String,
    #[serde(skip)]
    linkedstr5: String,
    #[serde(skip)]
    linkedstr6: String,
    #[serde(skip)]
    linkedstr7: String,
    #[serde(skip)]
    linkedstr8: String,
    #[serde(skip)]
    linkedstr9: String,
    #[serde(skip)]
    detected: bool,
    #[serde(skip)]
    fired: bool,
    #[serde(skip)]
    state: LightState,
}

impl Light {
    fn new() -> Light {
        Light {
            name: String::new(),
            mac: [0; 6],
            linked_mac0: None,
            linked_mac1: None,
            linked_mac2: None,
            linked_mac3: None,
            linked_mac4: None,
            linked_mac5: None,
            linked_mac6: None,
            linked_mac7: None,
            linked_mac8: None,
            linked_mac9: None,
            namestr: String::new(),
            macstr: String::new(),
            linkedstr0: String::new(),
            linkedstr1: String::new(),
            linkedstr2: String::new(),
            linkedstr3: String::new(),
            linkedstr4: String::new(),
            linkedstr5: String::new(),
            linkedstr6: String::new(),
            linkedstr7: String::new(),
            linkedstr8: String::new(),
            linkedstr9: String::new(),
            detected: false,
            fired: false,
            state: LightState::Idle {
                edit_button: button::State::new(),
            },
        }
    }

    fn update(&mut self, msg: LightMessage) {
        match msg {
            LightMessage::Edit => {
                self.state = LightState::Editing {
                    edit_button: button::State::new(),
                    name: text_input::State::new(),
                    mac: text_input::State::new(),
                    linked_mac0: text_input::State::new(),
                    linked_mac1: text_input::State::new(),
                    linked_mac2: text_input::State::new(),
                    linked_mac3: text_input::State::new(),
                    linked_mac4: text_input::State::new(),
                    linked_mac5: text_input::State::new(),
                    linked_mac6: text_input::State::new(),
                    linked_mac7: text_input::State::new(),
                    linked_mac8: text_input::State::new(),
                    linked_mac9: text_input::State::new(),
                    delete_button: button::State::new(),
                };
                self.namestr.clone_from(&self.name);
                mac_to_string(&self.mac, &mut self.macstr);
                if match &self.linked_mac0 {
                    Some(l) => !mac_to_string(l, &mut self.linkedstr0),
                    None => true,
                } {
                    *(&mut self.linkedstr0) = String::new();
                };
                if match &self.linked_mac1 {
                    Some(l) => !mac_to_string(l, &mut self.linkedstr1),
                    None => true,
                } {
                    *(&mut self.linkedstr1) = String::new();
                };
                if match &self.linked_mac2 {
                    Some(l) => !mac_to_string(l, &mut self.linkedstr2),
                    None => true,
                } {
                    *(&mut self.linkedstr2) = String::new();
                };
                if match &self.linked_mac3 {
                    Some(l) => !mac_to_string(l, &mut self.linkedstr3),
                    None => true,
                } {
                    *(&mut self.linkedstr3) = String::new();
                };
                if match &self.linked_mac4 {
                    Some(l) => !mac_to_string(l, &mut self.linkedstr4),
                    None => true,
                } {
                    *(&mut self.linkedstr4) = String::new();
                };
                if match &self.linked_mac5 {
                    Some(l) => !mac_to_string(l, &mut self.linkedstr5),
                    None => true,
                } {
                    *(&mut self.linkedstr5) = String::new();
                };
                if match &self.linked_mac6 {
                    Some(l) => !mac_to_string(l, &mut self.linkedstr6),
                    None => true,
                } {
                    *(&mut self.linkedstr6) = String::new();
                };
                if match &self.linked_mac7 {
                    Some(l) => !mac_to_string(l, &mut self.linkedstr7),
                    None => true,
                } {
                    *(&mut self.linkedstr7) = String::new();
                };
                if match &self.linked_mac8 {
                    Some(l) => !mac_to_string(l, &mut self.linkedstr8),
                    None => true,
                } {
                    *(&mut self.linkedstr8) = String::new();
                };
                if match &self.linked_mac9 {
                    Some(l) => !mac_to_string(l, &mut self.linkedstr9),
                    None => true,
                } {
                    *(&mut self.linkedstr9) = String::new();
                };
            }
            LightMessage::EditFinish => {
                self.name.clone_from(&self.namestr);
                string_to_mac(&self.macstr, &mut self.mac);
                string_to_mac_option(&self.linkedstr0, &mut self.linked_mac0);
                string_to_mac_option(&self.linkedstr1, &mut self.linked_mac1);
                string_to_mac_option(&self.linkedstr2, &mut self.linked_mac2);
                string_to_mac_option(&self.linkedstr3, &mut self.linked_mac3);
                string_to_mac_option(&self.linkedstr4, &mut self.linked_mac4);
                string_to_mac_option(&self.linkedstr5, &mut self.linked_mac5);
                string_to_mac_option(&self.linkedstr6, &mut self.linked_mac6);
                string_to_mac_option(&self.linkedstr7, &mut self.linked_mac7);
                string_to_mac_option(&self.linkedstr8, &mut self.linked_mac8);
                string_to_mac_option(&self.linkedstr9, &mut self.linked_mac9);
                self.state = LightState::Idle {
                    edit_button: button::State::new(),
                };
            }
            LightMessage::NameEdited(s) => {
                self.namestr = s;
            }
            LightMessage::MACEdited(s) => {
                self.macstr = s;
            }
            LightMessage::LinkMACEdited(i, s) => match i {
                0 => self.linkedstr0 = s,
                1 => self.linkedstr1 = s,
                2 => self.linkedstr2 = s,
                3 => self.linkedstr3 = s,
                4 => self.linkedstr4 = s,
                5 => self.linkedstr5 = s,
                6 => self.linkedstr6 = s,
                7 => self.linkedstr7 = s,
                8 => self.linkedstr8 = s,
                9 => self.linkedstr9 = s,
                _ => (),
            },
            LightMessage::NameEditedFinish => {
                self.name.clone_from(&self.namestr);
            }
            LightMessage::MACEditedFinish => {
                string_to_mac(&self.macstr, &mut self.mac);
            }
            LightMessage::LinkMACEditedFinish(i) => {
                match i {
                    0 => string_to_mac_option(&self.linkedstr0, &mut self.linked_mac0),
                    1 => string_to_mac_option(&self.linkedstr1, &mut self.linked_mac1),
                    2 => string_to_mac_option(&self.linkedstr2, &mut self.linked_mac2),
                    3 => string_to_mac_option(&self.linkedstr3, &mut self.linked_mac3),
                    4 => string_to_mac_option(&self.linkedstr4, &mut self.linked_mac4),
                    5 => string_to_mac_option(&self.linkedstr5, &mut self.linked_mac5),
                    6 => string_to_mac_option(&self.linkedstr6, &mut self.linked_mac6),
                    7 => string_to_mac_option(&self.linkedstr7, &mut self.linked_mac7),
                    8 => string_to_mac_option(&self.linkedstr8, &mut self.linked_mac8),
                    9 => string_to_mac_option(&self.linkedstr9, &mut self.linked_mac9),
                    _ => false,
                };
            }
            _ => (),
        };
    }

    fn view(&mut self, index: usize) -> Element<Message> {
        let detected = self.detected;
        let fired = self.fired;
        match &mut self.state {
            LightState::Idle { edit_button } => Row::new()
                .align_items(Align::Center)
                .push(Self::state_echo(detected, fired))
                .push(Space::with_width(Length::Units(20)))
                .push(Text::new(&self.name))
                .push(
                    Button::new(edit_button, edit_icon())
                        .on_press(Message::Light(index, LightMessage::Edit))
                        .padding(7)
                        .style(style::Button::Icon),
                )
                .into(),
            LightState::Editing {
                name,
                mac,
                delete_button,
                edit_button,
                linked_mac0,
                linked_mac1,
                linked_mac2,
                linked_mac3,
                linked_mac4,
                linked_mac5,
                linked_mac6,
                linked_mac7,
                linked_mac8,
                linked_mac9,
            } => {
                let name_row = Row::new()
                    .padding(5)
                    .align_items(Align::Center)
                    .push(Self::state_echo(detected, fired))
                    .push(Text::new("Name:  "))
                    .push(
                        TextInput::new(name, "Describe the name", &self.namestr, move |x| {
                            Message::Light(index, LightMessage::NameEdited(x))
                        })
                        .padding(3)
                        .size(20)
                        .on_submit(Message::Light(index, LightMessage::NameEditedFinish)),
                    )
                    .push(
                        Button::new(edit_button, edit_icon())
                            .on_press(Message::Light(index, LightMessage::EditFinish))
                            .padding(10)
                            .style(style::Button::Icon),
                    );
                Column::new()
                    .push(name_row)
                    .push(
                        Self::row_with_name(
                            "MAC:  ",
                            mac,
                            "Describe the MAC",
                            &self.macstr,
                            move |x| Message::Light(index, LightMessage::MACEdited(x)),
                            Message::Light(index, LightMessage::MACEditedFinish),
                        )
                        .push(Space::with_width(Length::Units(20)))
                        .push(
                            Button::new(delete_button, delete_icon())
                                .on_press(Message::Light(index, LightMessage::Delete))
                                .style(style::Button::Destructive),
                        ),
                    )
                    .push(Self::row_with_name(
                        "Linked MAC0:  ",
                        linked_mac0,
                        "Describe the Linked MAC",
                        &self.linkedstr0,
                        move |x| Message::Light(index, LightMessage::LinkMACEdited(0, x)),
                        Message::Light(index, LightMessage::LinkMACEditedFinish(0)),
                    ))
                    .push(Self::row_with_name(
                        "Linked MAC1:  ",
                        linked_mac1,
                        "Describe the Linked MAC",
                        &self.linkedstr1,
                        move |x| Message::Light(index, LightMessage::LinkMACEdited(1, x)),
                        Message::Light(index, LightMessage::LinkMACEditedFinish(1)),
                    ))
                    .push(Self::row_with_name(
                        "Linked MAC2:  ",
                        linked_mac2,
                        "Describe the Linked MAC",
                        &self.linkedstr2,
                        move |x| Message::Light(index, LightMessage::LinkMACEdited(2, x)),
                        Message::Light(index, LightMessage::LinkMACEditedFinish(2)),
                    ))
                    .push(Self::row_with_name(
                        "Linked MAC3:  ",
                        linked_mac3,
                        "Describe the Linked MAC",
                        &self.linkedstr3,
                        move |x| Message::Light(index, LightMessage::LinkMACEdited(3, x)),
                        Message::Light(index, LightMessage::LinkMACEditedFinish(3)),
                    ))
                    .push(Self::row_with_name(
                        "Linked MAC4:  ",
                        linked_mac4,
                        "Describe the Linked MAC",
                        &self.linkedstr4,
                        move |x| Message::Light(index, LightMessage::LinkMACEdited(4, x)),
                        Message::Light(index, LightMessage::LinkMACEditedFinish(4)),
                    ))
                    .push(Self::row_with_name(
                        "Linked MAC5:  ",
                        linked_mac5,
                        "Describe the Linked MAC",
                        &self.linkedstr5,
                        move |x| Message::Light(index, LightMessage::LinkMACEdited(5, x)),
                        Message::Light(index, LightMessage::LinkMACEditedFinish(5)),
                    ))
                    .push(Self::row_with_name(
                        "Linked MAC6:  ",
                        linked_mac6,
                        "Describe the Linked MAC",
                        &self.linkedstr6,
                        move |x| Message::Light(index, LightMessage::LinkMACEdited(6, x)),
                        Message::Light(index, LightMessage::LinkMACEditedFinish(6)),
                    ))
                    .push(Self::row_with_name(
                        "Linked MAC7:  ",
                        linked_mac7,
                        "Describe the Linked MAC",
                        &self.linkedstr7,
                        move |x| Message::Light(index, LightMessage::LinkMACEdited(7, x)),
                        Message::Light(index, LightMessage::LinkMACEditedFinish(7)),
                    ))
                    .push(Self::row_with_name(
                        "Linked MAC8:  ",
                        linked_mac8,
                        "Describe the Linked MAC",
                        &self.linkedstr8,
                        move |x| Message::Light(index, LightMessage::LinkMACEdited(8, x)),
                        Message::Light(index, LightMessage::LinkMACEditedFinish(8)),
                    ))
                    .push(Self::row_with_name(
                        "Linked MAC9:  ",
                        linked_mac9,
                        "Describe the Linked MAC",
                        &self.linkedstr9,
                        move |x| Message::Light(index, LightMessage::LinkMACEdited(9, x)),
                        Message::Light(index, LightMessage::LinkMACEditedFinish(9)),
                    ))
                    .into()
            }
        }
    }

    fn state_echo(detected: bool, fired: bool) -> Text {
        if detected {
            Text::new("Detected  ").color([0.0, 1.0, 0.6])
        } else if fired {
            Text::new("Fired     ").color([0.8, 0.8, 0.0])
        } else {
            Text::new("Free      ").color([0.0, 0.7, 0.7])
        }
    }

    fn row_with_name<'a, F>(
        text: &'a str,
        state: &'a mut text_input::State,
        holder: &'a str,
        string: &'a str,
        on: F,
        submit: Message,
    ) -> Row<'a, Message>
    where
        F: 'static + Fn(String) -> Message,
    {
        Row::new()
            .padding(3)
            .align_items(Align::Center)
            .push(Text::new(text))
            .push(
                TextInput::new(state, holder, string, on)
                    .size(20)
                    .padding(3)
                    .on_submit(submit),
            )
    }

    fn matched(&self, mac: &String) -> bool {
        let mut temp = [0u8; 6];
        string_to_mac(mac, &mut temp);
        self.mac[0] == *&temp[0]
            && self.mac[1] == *&temp[1]
            && self.mac[2] == *&temp[2]
            && self.mac[3] == *&temp[3]
            && self.mac[4] == *&temp[4]
            && self.mac[5] == *&temp[5]
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Filter {
    All,
    Detected,
    Fired,
    Free,
}

impl Default for Filter {
    fn default() -> Self {
        Filter::All
    }
}

impl Filter {
    fn matches(&self, light: &Light) -> bool {
        match self {
            Filter::All => true,
            Filter::Detected => light.detected,
            Filter::Fired => light.fired,
            Filter::Free => !light.fired,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SavedState {
    lights: Vec<Light>,
}

#[derive(Debug, Clone)]
pub enum LoadError {
    FileError,
    FormatError,
    CipherError,
}

#[derive(Debug, Clone)]
pub enum SaveError {
    FileError,
    FormatError,
}

impl SavedState {
    async fn load(key: [u8; 16]) -> Result<SavedState, LoadError> {
        use async_std::prelude::*;
        let ciphertext = async_std::fs::read("./save.wisight")
            .await
            .map_err(|_| LoadError::FileError)?;
        let iv = hex!("f0e1f2f3f4faf6f7f4f9fafbfcfdfeff");
        let cipher = AesCbc::new_var(&key, &iv).unwrap();
        let mut buf = ciphertext;
        let decrypted_ciphertext = cipher
            .decrypt(&mut buf)
            .map_err(|_| LoadError::CipherError)?;
        let plaintext = String::from_utf8(decrypted_ciphertext.to_vec())
            .ok()
            .unwrap();
        serde_json::from_str(&plaintext).map_err(|_| LoadError::FormatError)
    }
    async fn save(self, key: [u8; 16]) -> Result<(), SaveError> {
        use async_std::prelude::*;
        let plaintext = serde_json::to_string_pretty(&self).map_err(|_| SaveError::FormatError)?;
        let iv = hex!("f0e1f2f3f4faf6f7f4f9fafbfcfdfeff");
        let cipher = AesCbc::new_var(&key, &iv).unwrap();
        let mut buffer = Vec::with_capacity(plaintext.len() + 32);
        for _i in 0..(plaintext.len() + 32) {
            buffer.push(0);
        }
        let pos = plaintext.len();
        buffer[..pos].copy_from_slice(plaintext.as_bytes());
        let ciphertext = cipher.encrypt(&mut buffer[..], pos).unwrap();
        async_std::fs::write("./save.wisight", &ciphertext)
            .await
            .map_err(|_| SaveError::FileError)?;
        async_std::task::sleep(std::time::Duration::from_secs(2)).await;
        Ok(())
    }
}

const ICONS: Font = Font::External {
    name: "Icons",
    bytes: include_bytes!("../fonts/icons.ttf"),
};

// Icon
fn icon(unicode: char) -> Text {
    Text::new(&unicode.to_string())
        .font(ICONS)
        .width(Length::Units(20))
        .horizontal_alignment(HorizontalAlignment::Center)
        .size(20)
}

fn edit_icon() -> Text {
    icon('\u{F303}')
}

fn delete_icon() -> Text {
    icon('\u{F1F8}')
}

// Utl
fn string_to_mac(string: &String, ptr: &mut [u8; 6]) -> bool {
    let mut temp: String = String::new();
    let mut res = true;
    temp.clone_from(string);
    let b: Vec<u8> = temp
        .as_bytes()
        .iter()
        .filter(|x| **x != 58 && **x != 32)
        .map(|x| {
            if *x < 58 && *x > 47 {
                x - 48
            } else if *x < 103 && *x > 96 {
                x - 87
            } else {
                res = false;
                0
            }
        })
        .collect();
    if b.len() != 12 {
        return false;
    }
    if res {
        for i in 0..6 {
            ptr[i] = b[i << 1] * 16 + b[(i << 1) + 1]
        }
    }
    res
}

fn string_to_mac_option(string: &String, ptr: &mut Option<[u8; 6]>) -> bool {
    let mut t = [0; 6];
    let ret = string_to_mac(string, &mut t);
    if ret {
        *ptr = Some(t);
    } else {
        *ptr = None;
    };
    ret
}

fn mac_to_string(ptr: &[u8; 6], string: &mut String) -> bool {
    let u8_to_char = |x: u8| {
        if x <= 9 {
            Some(x + 48)
        } else if 10 <= x && x <= 15 {
            Some(x + 87)
        } else {
            None
        }
    };
    let mut temp = vec![
        0, 0, ':' as u8, ' ' as u8, 0, 0, ':' as u8, ' ' as u8, 0, 0, ':' as u8, ' ' as u8, 0, 0,
        ':' as u8, ' ' as u8, 0, 0, ':' as u8, ' ' as u8, 0, 0,
    ];
    temp[0] = match u8_to_char(ptr[0] / 16) {
        Some(x) => x,
        None => return false,
    };
    temp[1] = match u8_to_char(ptr[0] % 16) {
        Some(x) => x,
        None => return false,
    };
    for i in 0..5 {
        temp[(i << 2) + 4] = match u8_to_char(ptr[i + 1] / 16) {
            Some(x) => x,
            None => return false,
        };
        temp[(i << 2) + 5] = match u8_to_char(ptr[i + 1] % 16) {
            Some(x) => x,
            None => return false,
        };
    }
    *string = match String::from_utf8(temp) {
        Ok(s) => s,
        Err(_) => return false,
    };
    true
}

// Async Network
fn send_block(send: &async_std::sync::Sender<SendMessage>, msg: SendMessage) {
    task::block_on(async move {
        send.send(msg).await;
    })
}

async fn accept_connection(addr: &str, port: u32) -> Option<(TcpStream, TcpStream)> {
    let addr = String::from(addr) + &String::from(format!(":{}", port));
    let listener = match TcpListener::bind(addr).await {
        Ok(t) => {
            println!("Succefully Listen");
            t
        }
        Err(e) => {
            println!("Fail To Open Listening Port Due To {:?}", e);
            return None;
        }
    };
    let mut incoming = listener.incoming();
    if let Some(wstream) = incoming.next().await {
        let send_stream = match wstream {
            Ok(t) => {
                println!("Succefully Accept Peer IP:{}", t.peer_addr().unwrap());
                t
            }
            Err(e) => {
                println!("Fail To Generate Write Stream {:?}", e);
                return None;
            }
        };
        task::sleep(Duration::from_millis(200)).await;
        let addr =
            send_stream.peer_addr().unwrap().ip().to_string() + &String::from(format!(":{}", port));
        let receive_stream = match TcpStream::connect(addr).await {
            Ok(t) => {
                println!("Succefully Connected Peer IP:{}", t.peer_addr().unwrap());
                t
            }
            Err(e) => {
                println!("Fail To Get Read Stream {:?}", e);
                return None;
            }
        };
        Some((send_stream, receive_stream))
    } else {
        None
    }
}

async fn inite(socket: TcpStream, lights: Vec<Light>) -> bool {
    let mut json_raw;
    let mut socket = socket;
    let mut buf = vec![0u8; 3];
    for i in lights {
        let Light {
            mac,
            linked_mac0,
            linked_mac1,
            linked_mac2,
            linked_mac3,
            linked_mac4,
            linked_mac5,
            linked_mac6,
            linked_mac7,
            linked_mac8,
            linked_mac9,
            ..
        } = i;
        let mut macstr = String::new();
        mac_to_string(&mac, &mut macstr);
        let mut linkmac = Vec::new();
        match linked_mac0 {
            Some(m) => {
                let mut linkmacstr = String::new();
                mac_to_string(&m, &mut linkmacstr);
                linkmac.push(Mac::new(linkmacstr));
            }
            None => {}
        };
        match linked_mac1 {
            Some(m) => {
                let mut linkmacstr = String::new();
                mac_to_string(&m, &mut linkmacstr);
                linkmac.push(Mac::new(linkmacstr));
            }
            None => {}
        };
        match linked_mac2 {
            Some(m) => {
                let mut linkmacstr = String::new();
                mac_to_string(&m, &mut linkmacstr);
                linkmac.push(Mac::new(linkmacstr));
            }
            None => {}
        };
        match linked_mac3 {
            Some(m) => {
                let mut linkmacstr = String::new();
                mac_to_string(&m, &mut linkmacstr);
                linkmac.push(Mac::new(linkmacstr));
            }
            None => {}
        };
        match linked_mac4 {
            Some(m) => {
                let mut linkmacstr = String::new();
                mac_to_string(&m, &mut linkmacstr);
                linkmac.push(Mac::new(linkmacstr));
            }
            None => {}
        };
        match linked_mac5 {
            Some(m) => {
                let mut linkmacstr = String::new();
                mac_to_string(&m, &mut linkmacstr);
                linkmac.push(Mac::new(linkmacstr));
            }
            None => {}
        };
        match linked_mac6 {
            Some(m) => {
                let mut linkmacstr = String::new();
                mac_to_string(&m, &mut linkmacstr);
                linkmac.push(Mac::new(linkmacstr));
            }
            None => {}
        };
        match linked_mac7 {
            Some(m) => {
                let mut linkmacstr = String::new();
                mac_to_string(&m, &mut linkmacstr);
                linkmac.push(Mac::new(linkmacstr));
            }
            None => {}
        };
        match linked_mac8 {
            Some(m) => {
                let mut linkmacstr = String::new();
                mac_to_string(&m, &mut linkmacstr);
                linkmac.push(Mac::new(linkmacstr));
            }
            None => {}
        };
        match linked_mac9 {
            Some(m) => {
                let mut linkmacstr = String::new();
                mac_to_string(&m, &mut linkmacstr);
                linkmac.push(Mac::new(linkmacstr));
            }
            None => {}
        };
        json_raw = Address {
            dest_addr: macstr,
            command: COMMAND_CONFIG,
            link_mac: linkmac,
        };
        let send_data = serde_json::to_string(&json_raw).unwrap().to_string();
        print!("{}", &send_data);
        match socket.write_all(send_data.as_bytes()).await {
            Err(_) => return false,
            _ => (),
        };
        match socket.read(&mut buf).await {
            Err(_) => return false,
            _ => (),
        };
        if *&buf[0] != 111 && *&buf[0] != 107 {
            println!("Fail to receive OK");
            return false;
        }
        println!("Light Successfully Configed, MAC: {:?}", &mac);
        task::sleep(Duration::from_millis(10)).await;
    }
    true
}

async fn config(socket: TcpStream, lights: Light) -> Option<(TcpStream, Light)> {
    let mut json_raw;
    let sockback = socket.clone();
    let lightback = lights.clone();
    let mut socket = socket;
    let mut buf = vec![0u8; 3];
    let Light {
        mac,
        linked_mac0,
        linked_mac1,
        linked_mac2,
        linked_mac3,
        linked_mac4,
        linked_mac5,
        linked_mac6,
        linked_mac7,
        linked_mac8,
        linked_mac9,
        ..
    } = lights;
    let mut macstr = String::new();
    mac_to_string(&mac, &mut macstr);
    let mut linkmac = Vec::new();
    match linked_mac0 {
        Some(m) => {
            let mut linkmacstr = String::new();
            mac_to_string(&m, &mut linkmacstr);
            linkmac.push(Mac::new(linkmacstr));
        }
        None => {}
    };
    match linked_mac1 {
        Some(m) => {
            let mut linkmacstr = String::new();
            mac_to_string(&m, &mut linkmacstr);
            linkmac.push(Mac::new(linkmacstr));
        }
        None => {}
    };
    match linked_mac2 {
        Some(m) => {
            let mut linkmacstr = String::new();
            mac_to_string(&m, &mut linkmacstr);
            linkmac.push(Mac::new(linkmacstr));
        }
        None => {}
    };
    match linked_mac3 {
        Some(m) => {
            let mut linkmacstr = String::new();
            mac_to_string(&m, &mut linkmacstr);
            linkmac.push(Mac::new(linkmacstr));
        }
        None => {}
    };
    match linked_mac4 {
        Some(m) => {
            let mut linkmacstr = String::new();
            mac_to_string(&m, &mut linkmacstr);
            linkmac.push(Mac::new(linkmacstr));
        }
        None => {}
    };
    match linked_mac5 {
        Some(m) => {
            let mut linkmacstr = String::new();
            mac_to_string(&m, &mut linkmacstr);
            linkmac.push(Mac::new(linkmacstr));
        }
        None => {}
    };
    match linked_mac6 {
        Some(m) => {
            let mut linkmacstr = String::new();
            mac_to_string(&m, &mut linkmacstr);
            linkmac.push(Mac::new(linkmacstr));
        }
        None => {}
    };
    match linked_mac7 {
        Some(m) => {
            let mut linkmacstr = String::new();
            mac_to_string(&m, &mut linkmacstr);
            linkmac.push(Mac::new(linkmacstr));
        }
        None => {}
    };
    match linked_mac8 {
        Some(m) => {
            let mut linkmacstr = String::new();
            mac_to_string(&m, &mut linkmacstr);
            linkmac.push(Mac::new(linkmacstr));
        }
        None => {}
    };
    match linked_mac9 {
        Some(m) => {
            let mut linkmacstr = String::new();
            mac_to_string(&m, &mut linkmacstr);
            linkmac.push(Mac::new(linkmacstr));
        }
        None => {}
    };
    json_raw = Address {
        dest_addr: macstr,
        command: COMMAND_CONFIG,
        link_mac: linkmac,
    };
    let send_data = serde_json::to_string(&json_raw).unwrap().to_string();
    print!("{}", &send_data);
    match socket.write_all(send_data.as_bytes()).await {
        Err(_) => {
            println!("Failed to Send Message to MESH");
            return Some((sockback, lightback));
        }
        _ => (),
    };
    match socket.read(&mut buf).await {
        Err(_) => {
            println!("Failed to Receive OK Response From MESH");
            return Some((sockback, lightback));
        }
        _ => (),
    };
    if *&buf[0] != 111 && *&buf[0] != 107 {
        println!("Fail to receive OK");
        return Some((sockback, lightback));
    }
    println!("Light Successfully Configed, MAC: {:?}", &mac);
    None
}

pub struct ESPListener {
    socket: TcpStream,
    hash_code: usize,
}

impl<H, I> iced_native::subscription::Recipe<H, I> for ESPListener
where
    H: std::hash::Hasher,
{
    type Output = Message;

    fn hash(&self, state: &mut H) {
        use std::hash::Hash;

        std::any::TypeId::of::<Self>().hash(state);
        state.write_usize(self.hash_code)
    }

    fn stream(
        self: Box<Self>,
        _input: futures::stream::BoxStream<'static, I>,
    ) -> futures::stream::BoxStream<'static, Self::Output> {
        let socket = self.socket.clone();
        Box::pin(futures::stream::unfold(socket, |mut state| async move {
            let mut buf = vec![0u8; 1024];
            match state.read(&mut buf).await {
                Err(e) => {
                    println!("Failed to Receive Message From MESH: {}", e);
                    return Some((Message::Empty, state));
                }
                _ => match state.write_all("ok".as_bytes()).await {
                    Err(e) => {
                        println!("Failed to Replay OK Message To MESH: {}", e);
                        return Some((Message::Empty, state));
                    }
                    _ => (),
                },
            };
            let plaintext = String::from_utf8(buf.to_vec()).ok().unwrap();
            let plaintext = plaintext.trim_matches(char::from(0));
            println!("{}", &plaintext);
            match serde_json::from_str(plaintext) {
                Ok(d) => Some((Message::RecvMessage(d), state)),
                Err(e) => {
                    println!("Receive JSON Format Error: {}", e);
                    Some((Message::Empty, state))
                }
            }
        }))
    }
}

mod style {
    use iced::{button, Background, Color, Vector};
    pub enum Button {
        Filter { selected: bool },
        Icon,
        Destructive,
        Primary,
        Secondary,
    }
    impl button::StyleSheet for Button {
        fn active(&self) -> button::Style {
            match self {
                Button::Filter { selected } => {
                    if *selected {
                        button::Style {
                            background: Some(Background::Color(Color::from_rgb(0.2, 0.2, 0.7))),
                            border_radius: 10,
                            text_color: Color::WHITE,
                            ..button::Style::default()
                        }
                    } else {
                        button::Style::default()
                    }
                }
                Button::Icon => button::Style {
                    text_color: Color::from_rgb(0.5, 0.5, 0.5),
                    ..button::Style::default()
                },
                Button::Destructive => button::Style {
                    background: Some(Background::Color(Color::from_rgb(0.8, 0.2, 0.2))),
                    border_radius: 5,
                    text_color: Color::WHITE,
                    shadow_offset: Vector::new(1.0, 1.0),
                    ..button::Style::default()
                },
                Button::Primary => button::Style {
                    background: Some(Background::Color(Color::from_rgb(0.11, 0.42, 0.87))),
                    border_radius: 12,
                    shadow_offset: Vector::new(1.0, 1.0),
                    text_color: Color::from_rgb8(0xEE, 0xEE, 0xEE),
                    ..button::Style::default()
                },
                Button::Secondary => button::Style {
                    background: Some(Background::Color(Color::from_rgb(0.5, 0.5, 0.5))),
                    border_radius: 12,
                    shadow_offset: Vector::new(1.0, 1.0),
                    text_color: Color::from_rgb8(0xEE, 0xEE, 0xEE),
                    ..button::Style::default()
                },
            }
        }
        fn hovered(&self) -> button::Style {
            let active = self.active();
            button::Style {
                text_color: match self {
                    Button::Icon => Color::from_rgb(0.2, 0.2, 0.7),
                    Button::Filter { selected } if !selected => Color::from_rgb(0.2, 0.2, 0.7),
                    _ => active.text_color,
                },
                shadow_offset: active.shadow_offset + Vector::new(0.0, 1.0),
                ..active
            }
        }
    }
}
